export class Texture {
  private gl: WebGLRenderingContext;
  private texture: WebGLTexture | null = null;
  private width: number = 0;
  private height: number = 0;

  constructor(gl: WebGLRenderingContext) {
    this.gl = gl;
  }

  async loadFromUrl(url: string): Promise<boolean> {
    return new Promise((resolve) => {
      const image = new Image();
      image.onload = () => {
        this.width = image.width;
        this.height = image.height;
        const success = this.loadFromImage(image);
        resolve(success);
      };
      image.onerror = () => {
        console.error(`加载纹理失败: ${url}`);
        resolve(false);
      };
      image.src = url;
    });
  }

  loadFromImage(image: HTMLImageElement): boolean {
    const gl = this.gl;
    
    // 创建纹理
    const texture = gl.createTexture();
    if (!texture) {
      console.error('创建纹理失败');
      return false;
    }
    
    // 绑定纹理
    gl.bindTexture(gl.TEXTURE_2D, texture);
    
    // 设置参数
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    
    // 上传图像数据
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
    
    // 保存纹理
    this.texture = texture;
    
    return true;
  }

  createEmptyTexture(width: number, height: number, hdr: boolean = false): boolean {
    const gl = this.gl;
    
    // 创建纹理
    const texture = gl.createTexture();
    if (!texture) {
      console.error('创建纹理失败');
      return false;
    }
    
    // 保存尺寸
    this.width = width;
    this.height = height;
    
    // 绑定纹理
    gl.bindTexture(gl.TEXTURE_2D, texture);
    
    // 设置参数
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    
    // 创建空纹理
    const internalFormat = gl.RGBA; // WebGL 1.0只支持RGBA
    const format = gl.RGBA;
    const type = hdr ? gl.FLOAT : gl.UNSIGNED_BYTE;
    
    gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, width, height, 0, format, type, null);
    
    // 保存纹理
    this.texture = texture;
    
    return true;
  }

  async loadCubemap(urls: string[]): Promise<boolean> {
    if (urls.length !== 6) {
      console.error('立方体贴图需要6个面的图像');
      return false;
    }

    const gl = this.gl;
    
    // 创建纹理
    const texture = gl.createTexture();
    if (!texture) {
      console.error('创建立方体贴图失败');
      return false;
    }
    
    // 绑定纹理
    gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
    
    // 设置参数
    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    // WebGL 1.0没有TEXTURE_WRAP_R参数
    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    
    // 加载每个面的图像
    const targets = [
      gl.TEXTURE_CUBE_MAP_POSITIVE_X,
      gl.TEXTURE_CUBE_MAP_NEGATIVE_X,
      gl.TEXTURE_CUBE_MAP_POSITIVE_Y,
      gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,
      gl.TEXTURE_CUBE_MAP_POSITIVE_Z,
      gl.TEXTURE_CUBE_MAP_NEGATIVE_Z
    ];
    
    // 加载所有面的图像
    try {
      const promises = urls.map((url, i) => {
        return new Promise<void>((resolve, reject) => {
          const image = new Image();
          image.onload = () => {
            gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
            gl.texImage2D(targets[i], 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
            resolve();
          };
          image.onerror = () => reject(new Error(`加载立方体贴图失败: ${url}`));
          image.src = url;
        });
      });
      
      await Promise.all(promises);
      
      // 保存纹理
      this.texture = texture;
      
      return true;
    } catch (error) {
      console.error(error);
      return false;
    }
  }

  bind(unit: number = 0): void {
    if (this.texture) {
      const gl = this.gl;
      gl.activeTexture(gl.TEXTURE0 + unit);
      gl.bindTexture(gl.TEXTURE_2D, this.texture);
    }
  }

  bindAsCubemap(unit: number = 0): void {
    if (this.texture) {
      const gl = this.gl;
      gl.activeTexture(gl.TEXTURE0 + unit);
      gl.bindTexture(gl.TEXTURE_CUBE_MAP, this.texture);
    }
  }

  getTexture(): WebGLTexture | null {
    return this.texture;
  }

  getWidth(): number {
    return this.width;
  }
  
  getHeight(): number {
    return this.height;
  }
} 